#include "Mesh.h"
#include "CurrentContext.h"

using namespace DirectX;

Mesh::Mesh()
{
  m_transparent = 0.5f;
  m_indexBuffer = 0;
  m_vertexBuffer = 0;
  ZeroMemory(&meshData, sizeof(meshData));
}

Mesh::Mesh(MeshDesc* meshDesc)
{
  m_transparent = 0.5f;
  XMStoreFloat4x4(&m_rotation, XMMatrixIdentity());
  XMStoreFloat4x4(&m_translation, XMMatrixIdentity());
  XMStoreFloat4x4(&m_transform, XMMatrixIdentity());

  memcpy(&this->meshData, meshDesc, sizeof(MeshDesc));
  
  D3D11_BUFFER_DESC vertexDesc;
  ZeroMemory(&vertexDesc, sizeof(vertexDesc));

  vertexDesc.Usage = D3D11_USAGE_DEFAULT;
  vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  vertexDesc.ByteWidth = sizeof(Vertex) * meshDesc->NumVertices;

  D3D11_SUBRESOURCE_DATA resourceData;
  ZeroMemory(&resourceData, sizeof(resourceData));
  resourceData.pSysMem = meshDesc->Vertices;

  CurrentContext::GetInstance().Device->CreateBuffer(&vertexDesc, &resourceData, &m_vertexBuffer);


  indexed = meshDesc->NumIndices > 0;
  if(indexed)
  {
    D3D11_BUFFER_DESC indexDesc;
    ZeroMemory( &indexDesc, sizeof( indexDesc ) );
    indexDesc.Usage = D3D11_USAGE_DEFAULT;
    indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    indexDesc.ByteWidth = sizeof( WORD ) * meshDesc->NumIndices;
    indexDesc.CPUAccessFlags = 0;
    resourceData.pSysMem = meshDesc->Indices;

    CurrentContext::GetInstance().Device->CreateBuffer(&indexDesc, &resourceData, &m_indexBuffer);
  }

  SetTranslation(0,0,0);
  SetRotation(0,0,0); 
}


Mesh::~Mesh(void)
{
}

XMMATRIX Mesh::GetWorldMatrix()
{
  return XMLoadFloat4x4(&m_transform);
}

void Mesh::UpdateTransformMatrix(bool updateAABB)
{
  XMMATRIX rot = XMLoadFloat4x4(&m_rotation);
  XMMATRIX pos = XMLoadFloat4x4(&m_translation);

  XMStoreFloat4x4(&m_transform, rot * pos);

  if(updateAABB)
    this->ComputeAABB(&this->meshData, m_transform);
}

void Mesh::SetTranslation(float x, float y, float z)
{
  XMMATRIX pos = XMMatrixTranslation(x, y, z);
  XMStoreFloat4x4(&m_translation, pos);

  this->UpdateTransformMatrix(false);
}

void Mesh::SetRotation(float x, float y, float z)
{
  XMMATRIX rot = XMMatrixRotationRollPitchYaw(x, y, z);
  XMStoreFloat4x4(&m_rotation, rot);
  this->UpdateTransformMatrix(true);
}

RenderDesc* Mesh::GetRenderData()
{
  static RenderDesc desc;
  desc.IndexBuffer = m_indexBuffer;
  desc.VertexBuffer = m_vertexBuffer;
  desc.TotalVertices = meshData.NumVertices;
  desc.TotalIndices = meshData.NumIndices;
  desc.TotalMaterials = meshData.NumMaterials;
  desc.Materials = meshData.Materials;
  return &desc;
}